package com.example.proxy.figen;

import com.example.proxy.anno.RestCompont;
import com.example.proxy.model.RestFactoryBean;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.util.ClassUtils;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class RestScanner extends ClassPathBeanDefinitionScanner {
    private final Map<String, Boolean> cacheData = new HashMap<>();

    public RestScanner(BeanDefinitionRegistry registry) {
        super(registry);
    }

    @Override
    protected void registerDefaultFilters() {
        this.addIncludeFilter(new AnnotationTypeFilter(RestCompont.class));
    }

    @Override
    protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Set<BeanDefinitionHolder> beanDefinitionHolders = super.doScan(basePackages);
        for (BeanDefinitionHolder beanDefinition : beanDefinitionHolders) {
            GenericBeanDefinition definition = (GenericBeanDefinition) beanDefinition.getBeanDefinition();
            definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName());
            definition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);
            definition.setBeanClass(RestFactoryBean.class);
        }
        return beanDefinitionHolders;
    }

    /**
     * 校验规则 1
     *
     * @param metadataReader
     * @return
     * @throws IOException
     */
    @Override
    protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
        String clzName = metadataReader.getAnnotationMetadata().getClassName();
        return this.check(clzName);
    }

    /**
     * 校验规则 2
     *
     * @param beanDefinition
     * @return
     */
    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        return this.check(beanDefinition.getBeanClassName());
    }

    /**
     * 校验规则
     *
     * @param clzName
     * @return
     */
    private boolean check(String clzName) {
        boolean flag = false;
        try {
            Class<?> clz = Class.forName(clzName);
            if (clz.isInterface() && clz.isAnnotationPresent(RestCompont.class)) {
                flag = true;
                cacheData.put(clzName, flag);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return flag;
    }
}
